package com.tsfyun.scm.service.impl.customer;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Snowflake;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tsfyun.common.base.config.OrikaBeanMapper;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.extension.OrderItem;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.common.base.security.SecurityUtil;
import com.tsfyun.common.base.util.StringUtils;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.common.base.util.TypeUtils;
import com.tsfyun.scm.dto.customer.SupplierBankDTO;
import com.tsfyun.scm.dto.customer.SupplierBankQTO;
import com.tsfyun.scm.dto.customer.client.ClientSupplierBankQTO;
import com.tsfyun.scm.entity.base.Currency;
import com.tsfyun.scm.entity.customer.Supplier;
import com.tsfyun.scm.entity.customer.SupplierBank;
import com.tsfyun.scm.mapper.customer.SupplierBankMapper;
import com.tsfyun.scm.service.base.ICurrencyService;
import com.tsfyun.scm.service.customer.ISupplierBankService;
import com.tsfyun.scm.service.customer.ISupplierService;
import com.tsfyun.scm.util.PermissionUtil;
import com.tsfyun.scm.util.TsfWeekendSqls;
import com.tsfyun.scm.vo.customer.SupplierBankVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.WeekendSqls;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *

 * @since 2020-03-12
 */
@Service
public class SupplierBankServiceImpl extends ServiceImpl<SupplierBank> implements ISupplierBankService {

    @Autowired
    private OrikaBeanMapper beanMapper;

    @Autowired
    private SupplierBankMapper supplierBankMapper;

    @Autowired
    private Snowflake snowflake;

    @Autowired
    private ISupplierService supplierService;

    @Autowired
    private ICurrencyService currencyService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addBatch(Long supplierId, List<SupplierBankDTO> banks) {
        if(CollectionUtil.isEmpty(banks)) {
            return;
        }
        Boolean isDefault = false;
        List<String> bankNams = Lists.newArrayList();
        for(int i=0;i<banks.size();i++){
            SupplierBankDTO supplierBankDTO = banks.get(i);
            String currencyName = supplierBankDTO.getCurrencyName();
            Currency currency = currencyService.findByName(currencyName);
            TsfPreconditions.checkArgument(Objects.nonNull(currency),new ServiceException(String.format("第【%d】条银行信息币制不存在",(i+1))));
            supplierBankDTO.setCurrencyId(currency.getId());
            if(supplierBankDTO.getIsDefault() && supplierBankDTO.getDisabled() != true){
                isDefault=true;
            }
            if(bankNams.contains(supplierBankDTO.getName())){
                throw new ServiceException(String.format("第【%d】条银行名称重复",(i+1)));
            }
            bankNams.add(supplierBankDTO.getName());
        }
        if(isDefault==false){
            //如果未勾选默认，则取第一条非启用数据
            for(int i=0;i<banks.size();i++) {
                SupplierBankDTO supplierBankDTO = banks.get(i);
                if (supplierBankDTO.getDisabled() != true) {
                    banks.get(i).setIsDefault(Boolean.TRUE);
                }
            }
        }
        List<SupplierBank> supplierBanks = Lists.newArrayListWithExpectedSize(banks.size());
        banks.stream().forEach(b->{
            SupplierBank r = new SupplierBank();
            r.setId(snowflake.nextId());
            r.setName(StringUtils.removeSpecialSymbol(b.getName()));
            r.setAccount(StringUtils.removeSpecialSymbol(b.getAccount()));
            r.setSwiftCode(StringUtils.removeSpecialSymbol(b.getSwiftCode()).toUpperCase());
            r.setCurrencyId(b.getCurrencyId());
            r.setCode(StringUtils.removeSpecialSymbol(b.getCode()));
            r.setAddress(StringUtils.removeSpecialSymbol(b.getAddress()));
            r.setDisabled(b.getDisabled());
            r.setIsDefault(b.getIsDefault());
            r.setSupplierId(supplierId);
            r.setDateCreated(LocalDateTime.now());
            r.setDateUpdated(r.getDateCreated());
            r.setCreateBy(SecurityUtil.getCurrentPersonIdAndName());
            r.setUpdateBy(r.getCreateBy());
            supplierBanks.add(r);
        });
        super.savaBatch(supplierBanks);
    }

    @Override
    public List<SupplierBank> list(Long supplierId) {
        SupplierBank supplierBank = new SupplierBank();
        supplierBank.setSupplierId(supplierId);
        return super.list(supplierBank);
    }

    @Override
    public List<SupplierBankVO> listBySupplierId(Long supplierId) {
        List<SupplierBankVO> supplierBankVOList = supplierBankMapper.listBySupplierId(supplierId);
        return supplierBankVOList;
    }

    @Override
    public void removeBySupplierId(Long supplierId) {
        supplierBankMapper.deleteByExample(Example.builder(SupplierBank.class).where(TsfWeekendSqls.<SupplierBank>custom().andEqualTo(false,SupplierBank::getSupplierId,supplierId)).build());
    }

    @Override
    public List<SupplierBankVO> select(Long supplierId) {
        List<SupplierBank> suppliers =  super.list(new SupplierBank().setSupplierId(supplierId).setDisabled(Boolean.FALSE));
        //按修改时间排序
        suppliers = suppliers.stream().sorted(Comparator.comparing(SupplierBank::getDateUpdated).reversed()).collect(Collectors.toList());
        return beanMapper.mapAsList(suppliers,SupplierBankVO.class);
    }

    @Override
    public List<SupplierBankVO> vague(Long customerId,String supplierName, String bankName) {
        if(Objects.isNull(customerId)||StringUtils.isEmpty(supplierName)){return Lists.newArrayList();}
        return supplierBankMapper.vague(customerId,supplierName,bankName);
    }

    @Override
    public SupplierBankVO getSupplierBankInfo(Long customerId, String supplierName, String bankName) {
        if(Objects.isNull(customerId)||StringUtils.isEmpty(supplierName)||StringUtils.isEmpty(bankName)){return null;}
        return supplierBankMapper.getSupplierBankInfo(customerId,supplierName,bankName);
    }

    @Override
    public SupplierBankVO accurate(Long customerId, String supplierName, String bankName) {
        if(Objects.nonNull(customerId)&&StringUtils.isEmpty(supplierName)){return null;}
        return supplierBankMapper.accurate(customerId,supplierName,bankName);
    }

    @Override
    public SupplierBankVO detail(Long id) {
        SupplierBank supplierBank = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(supplierBank),new ServiceException("供应商银行信息不存在"));
        //返回币制名称
        Currency currency = currencyService.findById(supplierBank.getCurrencyId());
        SupplierBankVO supplierBankVO = beanMapper.map(supplierBank,SupplierBankVO.class);
        supplierBankVO.setCurrencyName(currency.getName());
        supplierBankVO.setSupplierName(supplierService.get(supplierBankVO.getSupplierId()).getName());
        return supplierBankVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateDisabled(Long id, Boolean disabled) {
        SupplierBank supplierBank = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(supplierBank),new ServiceException("供应商银行信息不存在"));
        SupplierBank update = new SupplierBank();
        update.setDisabled(disabled);
        //同时取消默认
        update.setIsDefault(Boolean.FALSE);
        supplierBankMapper.updateByExampleSelective(update, Example.builder(SupplierBank.class).where(
                WeekendSqls.<SupplierBank>custom().andEqualTo(SupplierBank::getId,id)
        ).build());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long add(SupplierBankDTO dto) {
        //如果前端未传是否默认，则默认为未勾选不默认
        dto.setIsDefault(TypeUtils.castToBoolean(dto.getIsDefault(),Boolean.FALSE));
        TsfPreconditions.checkArgument(Objects.nonNull(dto.getSupplierId()),new ServiceException("请选择供应商"));
        Supplier supplier = supplierService.getById(dto.getSupplierId());
        TsfPreconditions.checkArgument(Objects.nonNull(supplier),new ServiceException("供应商信息不存在"));
        //校验币制是否存在
        String currencyName = dto.getCurrencyName();
        Currency currency = currencyService.findByName(currencyName);
        TsfPreconditions.checkArgument(Objects.nonNull(currency),new ServiceException("币制不存在"));
        //校验银行名称是否存在
        SupplierBank queryBank = new SupplierBank();
        queryBank.setSupplierId(supplier.getId());
        queryBank.setName(dto.getName());
        int nameCnt = super.count(queryBank);
        TsfPreconditions.checkArgument(nameCnt < 1,new ServiceException(String.format("供应商已经存在银行名称【%s】的银行信息",dto.getName())));

        //如果勾选了默认，则需要取消以前设置的默认
        if(Objects.equals(dto.getIsDefault(),Boolean.TRUE)) {
            handleOldDefault(supplier.getId());
        }
        if(Objects.equals(Boolean.TRUE,dto.getIsDefault())) {
            dto.setDisabled(Boolean.FALSE);
        }
        SupplierBank supplierBank = new SupplierBank();
        supplierBank.setSupplierId(supplier.getId());
        supplierBank.setName(StringUtils.removeSpecialSymbol(dto.getName()))
                    .setCurrencyId(currency.getId())
                    .setAccount(StringUtils.removeSpecialSymbol(dto.getAccount()))
                    .setSwiftCode(StringUtils.removeSpecialSymbol(dto.getSwiftCode()).toUpperCase())
                    .setCode(dto.getCode())
                    .setAddress(StringUtils.removeSpecialSymbol(dto.getAddress()))
                    .setDisabled(dto.getDisabled())
                    .setIsDefault(dto.getIsDefault());
        super.saveNonNull(supplierBank);
        return supplierBank.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long clientAdd(SupplierBankDTO dto) {
        TsfPreconditions.checkArgument(StringUtils.isNotEmpty(dto.getSupplierName()),new ServiceException("请选择供应商"));
        Supplier supplier = supplierService.findByCustomerIdAndSupplierName(SecurityUtil.getCurrentCustomerId(),dto.getSupplierName());
        TsfPreconditions.checkArgument(Objects.nonNull(supplier),new ServiceException("供应商信息不存在"));
        dto.setSupplierId(supplier.getId());
        dto.setDisabled(Boolean.FALSE);
        return add(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void clientEdit(SupplierBankDTO dto) {
        TsfPreconditions.checkArgument(StringUtils.isNotEmpty(dto.getSupplierName()),new ServiceException("请选择供应商"));
        Supplier supplier = supplierService.findByCustomerIdAndSupplierName(SecurityUtil.getCurrentCustomerId(),dto.getSupplierName());
        TsfPreconditions.checkArgument(Objects.nonNull(supplier),new ServiceException("供应商信息不存在"));
        dto.setSupplierId(supplier.getId());
        edit(dto);
    }

    public void handleOldDefault(Long supplierId) {
        SupplierBank update = new SupplierBank();
        update.setIsDefault(Boolean.FALSE);
        supplierBankMapper.updateByExampleSelective(update, Example.builder(SupplierBank.class).where(TsfWeekendSqls.<SupplierBank>custom()
                .andEqualTo(false,SupplierBank::getSupplierId, supplierId)
                .andEqualTo(false,SupplierBank::getIsDefault,Boolean.TRUE)).build());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(SupplierBankDTO dto) {
        //如果前端未传是否默认，则默认为未勾选不默认
        dto.setIsDefault(TypeUtils.castToBoolean(dto.getIsDefault(),Boolean.FALSE));
        TsfPreconditions.checkArgument(Objects.nonNull(dto.getId()),new ServiceException("请选择需要修改的数据"));
        TsfPreconditions.checkArgument(Objects.nonNull(dto.getSupplierId()),new ServiceException("请选择供应商"));
        Supplier supplier = supplierService.getById(dto.getSupplierId());
        TsfPreconditions.checkArgument(Objects.nonNull(supplier),new ServiceException("供应商信息不存在"));
        SupplierBank oldSupplierBank = super.getById(dto.getId());
        TsfPreconditions.checkArgument(Objects.nonNull(oldSupplierBank),new ServiceException("供应商银行信息不存在"));
        //校验币制是否存在
        String currencyName = dto.getCurrencyName();
        Currency currency = currencyService.findByName(currencyName);
        TsfPreconditions.checkArgument(Objects.nonNull(currency),new ServiceException("币制不存在"));

        int supplierBankNameCnt = supplierBankMapper.selectCountByExample(Example.builder(SupplierBank.class).where(
                TsfWeekendSqls.<SupplierBank>custom().andNotEqualTo(false,SupplierBank::getId, dto.getId())
                        .andEqualTo(false,SupplierBank::getSupplierId,supplier.getId())
                        .andEqualTo(false,SupplierBank::getName,dto.getName())).build());
        TsfPreconditions.checkArgument(supplierBankNameCnt < 1,new ServiceException(String.format("供应商已经存在银行名称【%s】的银行信息",dto.getName())));

        //如果由非默认变为默认则需要处理之前设置的默认的，如果是否默认未变更则无需处理；
        if (!Objects.equals(Boolean.TRUE,oldSupplierBank.getIsDefault()) && Objects.equals(Boolean.TRUE,dto.getIsDefault())) {
            handleOldDefault(supplier.getId());
        }
        if(Objects.equals(Boolean.TRUE,dto.getIsDefault())) {
            dto.setDisabled(Boolean.FALSE);
        }

        SupplierBank supplierBank = oldSupplierBank;
        supplierBank.setSupplierId(supplier.getId());
        supplierBank.setName(StringUtils.removeSpecialSymbol(dto.getName()))
                .setAccount(StringUtils.removeSpecialSymbol(dto.getAccount()))
                .setCurrencyId(currency.getId())
                .setSwiftCode(StringUtils.removeSpecialSymbol(dto.getSwiftCode()).toUpperCase())
                .setCode(StringUtils.removeSpecialSymbol(dto.getCode()))
                .setAddress(StringUtils.removeSpecialSymbol(dto.getAddress()))
                .setDisabled(dto.getDisabled())
                .setIsDefault(dto.getIsDefault());
        super.updateById(supplierBank);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void remove(Long id) {
        SupplierBank supplierBank = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(supplierBank),new ServiceException("供应商银行信息不存在"));
        //删除供应商银行信息，数据冗余到具体的业务表
        super.removeById(id);
    }

    @Override
    public int countBySupplierId(Long supplierId) {
        return supplierBankMapper.selectCountByExample(Example.builder(SupplierBank.class).where(TsfWeekendSqls.<SupplierBank>custom().andEqualTo(true,SupplierBank::getSupplierId,supplierId)).build());
    }

    @Override
    public PageInfo<SupplierBankVO> pageList(SupplierBankQTO qto) {
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        Map<String,Object> params = beanMapper.map(qto,Map.class);
        return new PageInfo<>(supplierBankMapper.list(params));
    }

    @Override
    public SupplierBank defSupplierBank(Long supplierId) {
        return supplierBankMapper.defSupplierBank(supplierId);
    }

    @Override
    public PageInfo<SupplierBank> clientPage(ClientSupplierBankQTO qto) {
        TsfWeekendSqls sqls = TsfWeekendSqls.<SupplierBank>custom()
                .andEqualTo(false,SupplierBank::getSupplierId,qto.getSupplierId())
                .andEqualTo(true,SupplierBank::getDisabled,qto.getDisabled());
        return super.pageList(qto.getPage(),qto.getLimit(),sqls,Lists.newArrayList(OrderItem.desc("isDefault"),OrderItem.asc("name")));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void clientRemove(Long id) {
        SupplierBank supplierBank = super.getById(id);
        Optional.ofNullable(supplierBank).orElseThrow(()->new ServiceException("供应商银行信息不存在，请确认是否已经被删除"));
        Supplier supplier = supplierService.getById(supplierBank.getSupplierId());
        PermissionUtil.checkClientCustomerPermission(supplier);
        super.removeById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void setDefault(Long id) {
        //无需前台传参，后台根据数据库的记录取反
        SupplierBank supplierBank = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(supplierBank),new ServiceException("供应商银行信息不存在"));
        Boolean currentDefault = supplierBank.getIsDefault();
        if(Objects.equals(Boolean.TRUE,currentDefault)) {
            //以前是默认，则现在无需操作
            return;
        } else {
            //以前是非默认，现在置为默认，则需要取消以前的默认如果存在的话
            supplierBank.setIsDefault(Boolean.TRUE);
            supplierBank.setDisabled(Boolean.FALSE);

            SupplierBank update = new SupplierBank();
            update.setIsDefault(Boolean.FALSE);

            supplierBankMapper.updateByExampleSelective(update, Example.builder(SupplierBank.class).where(WeekendSqls.<SupplierBank>custom()
                    .andEqualTo(SupplierBank::getSupplierId, supplierBank.getSupplierId())
                    .andEqualTo(SupplierBank::getIsDefault,Boolean.TRUE)).build());
        }
        super.updateById(supplierBank);
    }
}
